///////////////////////////////////////////////////////////////////////////////
//File Name			:	"CGame.h"
//////////////////////////////////////////////////////////////////////////////
#ifndef CGAME_H_
#define CGAME_H_


#include <windows.h>
#include "Game States/BaseGameState.h"
#include <process.h>
#include "Event System/IListener.h"
#include "Memory Manager/MemoryProfessor.h"

#include <string>
#include <vector>
#include <deque>


////////////////////////
// Renderer
#include "Render/RenderMaster.h"


#pragma comment(lib,"user32.lib")

using std::string;

class CDebugConsole;
class CEventManager;
class deltaTimer;
class CObjectFactory;
class CObjectManager;

class CGame: public IListener
{
private:
	
	//constructor
	CGame();
	//trilogy of evil
	CGame(const CGame&);
	//copy constructor
	CGame& operator =(const CGame&);
	//assigment operator
	~CGame();
	//destructor

	//3 steps ggo though execution
	//input

	bool Input();
	
	//Render
	void Render();
	
	//vector of Base states
	std::vector<CBaseGameState*> m_vVectorStates;
	
	//Boolean to let the thread know is time to go
	volatile bool	m_bTimeToLeave;	
	
	//Console Debug
	CDebugConsole* m_Console;

	//Internaly Initialize all CGame components
	void InternalInitialize();

	// HELLO VICTOR!
	CRenderMaster* m_pRenderer;

	//Object Manager
	CObjectManager* m_pObjectManager;

	//Object Factory
	CObjectFactory* m_pObjectFactory;

private:
	float* updateCounter;

	unsigned int* unlockPerformance;

	//Thread
	HANDLE	ThreadHandle;

	//Critical Section
	CRITICAL_SECTION* LockSection;

	//Function to do lock and Unlock the thread
	void LockIt()
	{
		EnterCriticalSection(LockSection);
	}
	void UnLockIt()
	{
		LeaveCriticalSection(LockSection);
	}

	//End Thread

public:
		//Event Manager
	CEventManager* EventManager;

	CMemoryProfessor MemoryManager;

	
	//Accesor Vector of States
	const std::vector<CBaseGameState*> GetVectorStates()
	{ 
		std::vector<CBaseGameState*> vTemp;
		unsigned int unsize = 0;

		LockIt();

			unsize = m_vVectorStates.size();
			vTemp.resize(unsize);

			for(unsigned int x =0; x < unsize; ++x)
			{
				vTemp[x] = m_vVectorStates[x];
			}

		UnLockIt();

		return vTemp;
	}

	//Accessor
	const bool GetIsShutDownTime()
	{
		bool bTemp;
		
		LockIt();
		bTemp = m_bTimeToLeave;
		UnLockIt();

		return bTemp;
	}
	
	CDebugConsole* GetConsole()
	{
		CDebugConsole* CTemp;
		
		LockIt();
		CTemp = m_Console;
		UnLockIt();

		return CTemp;
	}


	//Mutator
	void SetShutDownTime(bool Rdy)
	{
		LockIt();
		m_bTimeToLeave = Rdy;
		UnLockIt();
	}
	
	const unsigned int GetUnlockPerformance(){return *unlockPerformance;}
	const float GetUpdateCounter(){return *updateCounter;}

	CObjectManager* GetObjectManager(){return m_pObjectManager;}
	CObjectFactory* GetObjectFactory(){return m_pObjectFactory;}

	void SetUnlockPerformance(const unsigned int val){*unlockPerformance=val;}
	void SetUpdateCounter(const float val){*updateCounter=val;}

	//
	void Push(CBaseGameState* pIGameState);
	//
	void PushNoEnter(CBaseGameState* pIGameState);
	//
	void Pop();
	//
	void ClearAllStates();
	//
	void ChangeState(CBaseGameState* pNewState);
	
	//Return the instance of the game class
	static CGame* GetInstance();

	//3 steps
	//Iniotialize
	void Initialize(HWND hWnd,HINSTANCE hInstance, int nScreenWidth, int nScreenHeight,bool bIsWindowed);
	
	//Execution
	//return false to quit game
	bool Main();
	
	//clean up
	void Shutdown(void);

	virtual void ProcessEvent(CEvent* pEvent);

	//Render Timer
	deltaTimer* m_fRenderTimer;

	//Update Timer
	deltaTimer* m_fUpdateTimer;



};
#endif